package org.springframework.howelly.controllers;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.howelly.helpers.GastoChart;
import org.springframework.howelly.helpers.SearchCriteria;
import org.springframework.howelly.model.Gasto;
import org.springframework.howelly.model.Obra;
import org.springframework.howelly.model.User;
import org.springframework.howelly.services.GastoService;
import org.springframework.howelly.utils.Constants;
import org.springframework.stereotype.Controller;
import org.springframework.webflow.execution.RequestContext;

@Controller
public class GastoController {

    private GastoService gastoService;

    @Autowired
    public GastoController(GastoService gastoService) {
	this.gastoService = gastoService;
    }

    public List<Gasto> findGastos(String username, long obraId, RequestContext context) {
	context.getFlowScope().remove("gastos");
	List<Gasto> results = gastoService.findGastos(username, obraId, context);
	calculateFooterValues(context, results);
	return results;
    }

    public List<Gasto> filtrarGastos(Gasto gasto, long obraId, RequestContext context) {
	try {
	    context.getFlowScope().remove("gastos");
	    List<Gasto> results = gastoService.filtrarGastos(gasto, obraId, context);
	    calculateFooterValues(context, results);
	    return results;
	} catch (ParseException e) {
	    e.printStackTrace();
	}
	return new ArrayList<Gasto>();
    }

    public List<Gasto> findGastosByFactura(SearchCriteria criteria) throws Exception {
	return gastoService.findGastosByFactura(criteria);

    }

    public Gasto createGasto(long obraId, String username) {
	return gastoService.createGasto(obraId, username);
    }

    public Gasto createIngreso(long obraId, String username) {
	return gastoService.createIngreso(obraId, username);
    }

    public Gasto resetValues(Obra obra) {
	Gasto gasto = new Gasto();
	gasto.setId(null);
	gasto.setName("");
	gasto.setDiaEfectuadoString("");
	gasto.setFactura("");
	gasto.setCategoriaName("");
	return gasto;
    }

    public Gasto calculateTotals(Gasto gasto, long obraId, RequestContext context) {
	return gastoService.calculateTotalsAndSave(gasto, obraId, context);
    }

    public ArrayList<GastoChart> gastosToGastosChart(String username, long obraId, RequestContext context) {
	ArrayList<GastoChart> gastosChart = new ArrayList<GastoChart>();
	List<Gasto> gastos = gastoService.findGastos(username, obraId, context);
	Collections.sort(gastos, Gasto.ByDate);
	BigDecimal saldoPorDia = BigDecimal.ZERO;
	if (gastos.get(0) != null) {
	    for (Gasto gasto : gastos) {
		GastoChart chart = new GastoChart(gasto);
		if (gasto.getExpenseType().equals(Constants.GASTO)) {
		    saldoPorDia = saldoPorDia.subtract(gasto.getPrice()).setScale(2, RoundingMode.HALF_DOWN);
		} else
		    saldoPorDia = saldoPorDia.add(gasto.getPrice()).setScale(2, RoundingMode.HALF_DOWN);
		chart.setSaldoParcial(saldoPorDia.doubleValue());
		gastosChart.add(chart);
	    }
	}
	Collections.sort(gastosChart, GastoChart.ByDate);
	context.getFlashScope().put("gastosChart", gastosChart);
	return gastosChart;
    }

    public boolean deleteGasto(String username, Gasto gasto, MessageContext context) {
	User user = gastoService.findUser(username);
	if (user.getRole().equals(Constants.ROLE_SUPERVISOR) || gasto.getUser().getName().equals(user.getName())) {
	    context.addMessage(new MessageBuilder().info().source("borrarGasto").defaultText(
		    "El " + gasto.getExpenseType() + " " + gasto.getName() + " ha sido borrado exitosamente").build());
	    return gastoService.deleteGasto(gasto);
	}
	context.addMessage(new MessageBuilder().error().source("borrarGasto").defaultText(
		"El usuario " + user.getName() + " no tiene permisos para borrar ese gasto ").build());
	// Voy a la misma pantalla que si se hubiese borrado
	return true;

    }

    public void calculateFooterValues(RequestContext context, List<Gasto> result) {
	double totalIngresos = 0;
	double totalGastos = 0;
	for (Gasto gasto : result) {
	    if (gasto.getExpenseType().equals(Constants.GASTO) && gasto.getPrice() != null) {
		totalGastos += gasto.getPrice().doubleValue();
	    } else if (gasto.getPrice() != null)
		totalIngresos += gasto.getPrice().setScale(2, RoundingMode.HALF_DOWN).doubleValue();
	}
	double saldoParcial = new BigDecimal(totalIngresos - totalGastos).setScale(2, RoundingMode.HALF_DOWN)
		.doubleValue();
	context.getFlashScope().put("totalIngresos", totalIngresos);
	context.getFlashScope().put("totalGasto", totalGastos);
	context.getFlashScope().put("saldo", saldoParcial);
    }

    public List<String> autoCompleteSuggestions(String query) {
	return gastoService.getNameOptions(query);

    }

    public GastoService getGastoService() {
	return gastoService;
    }
}
